import * as vscode from 'vscode';
import * as path from 'path';
import { Definitions, SnippetDefinition, NameAndPos, PathMap, TestCase, FunctionInfo, DefsInFunc, FuncCalledInfo } from "../entities/types";
import { getEOL } from '../utils/utils';
import { waitForTimeout } from '../utils/utils';
import { CxxLanguageServer } from '../services/CxxLanguageServer';
import { DefinitionType } from '../entities/enum';
import { ClassifyDefinitionsProcessor } from './ClassifyDefinitionsProcessor';
import { TreeSitter } from '../../../../core/treesitter/TreeSitter';

// 使用 any 避免 web-tree-sitter 类型定义问题
type SyntaxNode = any;
import { Logger } from '../../../../src/logger/Logger';

const TIMEOUT_MS = 4000;

export class CxxCustomizationProcessor {
  private static languageServer = CxxLanguageServer.getInstance();
  private static treeSitterParser = TreeSitter.getInstance();

  public static async getSnippetDefinitions(
    doc: vscode.TextDocument,
    funcRange: vscode.Range,
    symbolDefinitions: Definitions,
    cancellationToken?: vscode.CancellationToken,
  ) {

    const { signatureRange } = ClassifyDefinitionsProcessor.getSignatureAndFucBodyRange(doc, funcRange);
    const signatureDefinitions: SnippetDefinition[] = await this.languageServer.getSnippetDefinition({
      document: doc,
      range: signatureRange,
      allowedTypes: ['struct', 'macro', 'typedef', 'class', 'union', 'enum', 'enumerator', 'variable'],
      token: cancellationToken
    });
    for (const def of signatureDefinitions) {
      const regexStruct = /^typedef(\s+)struct/g;
      const regexEnum = /^typedef(\s+)enum/g;
      if (def.type === DefinitionType.typedef && regexStruct.test(def.text)) {
        const structDef = symbolDefinitions.struct.find(item => item.name === def.name);
        !structDef && symbolDefinitions.struct.push(def);
      } else if (def.type === DefinitionType.typedef && regexEnum.test(def.text)) {
        const enumDef = symbolDefinitions.enum.find(item => item.name === def.name);
        !enumDef && symbolDefinitions.enum.push(def);
      } else {
        symbolDefinitions[def.type as keyof Definitions]!.push(def);
      }
    }
  }

  public static getUsingNamespace(paramNamespace: string[], classNamespace: string): string {
    if (!paramNamespace.length) {
      return '';
    }
    let usingNamespace = '';
    for (let index = 0; index < paramNamespace.length; index++) {
      const item = paramNamespace[index];
      if (item === classNamespace) {
        continue;
      };
      usingNamespace = usingNamespace + `\r\nusing namespace ${item}${index === paramNamespace.length - 1 ? '' : ';'}`;
    }
    return usingNamespace;
  }

  public static async parseSignature(
    doc: vscode.TextDocument,
    range: vscode.Range,
    functionInfo: FunctionInfo) {
    // 提供一个空实现，使以下两种情况都被解析成function_declarator，否则
    const tree = this.treeSitterParser.getTree(functionInfo.signature + ' {}', doc.languageId);
    if (tree) {
      const rootNode = tree.rootNode;
      const functionName = ClassifyDefinitionsProcessor.getFunctionName(rootNode, range.start);
      functionInfo.sourceFunc = functionName;
    }
  }

  public static async getIncludeStatment(doc: vscode.TextDocument,
    definitionInFunction: DefsInFunc,
    funcInfo: FunctionInfo
  ): Promise<{ includeStr: string, filterReferences: vscode.Location[] }> {
    const start = Date.now(); // 记录开始时间
      Logger.info(`getIncludeStatment start.`);
    let includeStr = '';
    const range = funcInfo.sourceFunc?.position;
    const funcSignature = funcInfo.signature;
    if (!range) {
      return { includeStr, filterReferences: [] };
    }
    const tree = this.treeSitterParser.getTree(doc.getText(), doc.languageId);
    if (!tree) {
      return { includeStr, filterReferences: [] };
    }
    // 获取被测函数所在头文件失败，导入入参、返回值所在头文件 + extern C语句
    const references = await this.languageServer.getDocumentReferences( doc, range.start);
    const includeList = this.treeSitterParser.getTargetNode(tree.rootNode, ['preproc_include']);
    let libList: string[] = [];
    includeList.map((node: SyntaxNode) => {
      const lib = this.treeSitterParser.getTargetNodeText(node, ['system_lib_string', 'string_literal']);
      libList = libList.concat(lib.map((item: string) => {
        return path.basename(item.replace(/["'"]/g, ''));
      }));
    });
    const filterReferences: vscode.Location[] = [];
    references.forEach(item => {
      if (libList.includes(path.basename(item.uri.path)) && !filterReferences.find(rItem => item?.uri?.path === rItem?.uri?.path)) {
        filterReferences.push(item);
      }
    })
    const paramsSourceHeaderFile = definitionInFunction.others.paramSourceHeaderFile;
    if (!filterReferences.length && funcSignature && paramsSourceHeaderFile?.length) {
      paramsSourceHeaderFile.forEach(item => {
        includeStr = includeStr + `#include "${item}" \r\n`;
      });
      includeStr = includeStr + `extern "C";\r\n${funcSignature}`;
    } else {
      filterReferences.forEach(item => {
        includeStr = includeStr + `#include "${path.basename(item.uri.path)}"\r\n`;
      });
    }
    const end = Date.now(); // 记录结束时间
    const executionTime = end - start; // 计算执行时间
      Logger.info(`getIncludeStatment success time cost: ${executionTime}ms.`);
    return { includeStr, filterReferences };
  }

  public static async getTemplateStatment(doc: vscode.TextDocument, funcInfo: FunctionInfo): Promise<{
    templateInstantiation: string
    templateDeclar: string
  }> {
    let templateInstantiation = '';
    let templateDeclar = '';
    const range = funcInfo.sourceFunc?.position;
    if (!range) {
      return { templateInstantiation, templateDeclar };
    }
    // 获取上一行是否有template
    const res = await ClassifyDefinitionsProcessor.findTemplateDeclaration(range, doc);
    templateDeclar = res?.templateText || '';
    const tree = this.treeSitterParser.getTree(doc.getText(), doc.languageId);
    if (!tree) {
      return { templateInstantiation, templateDeclar };
    }
    // 获取与当前函数匹配的template
    const templateList = this.treeSitterParser.getTargetNode(tree.rootNode, ['template_instantiation']);
    for (const node of templateList) {
      const name = ClassifyDefinitionsProcessor.getFunctionName(node, new vscode.Position(node.startPosition.row, node.endPosition.column));
      if (name?.name === funcInfo.sourceFuncName) {
        templateInstantiation = node.text;
      }
    }
    return { templateInstantiation, templateDeclar };
  }

  public static async handleSourceMethod(functionInfo: FunctionInfo,
    definitionInFunction: DefsInFunc,
    allGmock: string[],
    allCppStub: string[],
    languageId: string,
  ): Promise<{
    constructorsMethod: string,
    classNameLower: string,
    gmockStr: string,
    cppstubStr: string,
    classFields: string,
  }> {
    const publicList = definitionInFunction.classCtors?.public || [];
    const classFields = definitionInFunction.classCtors?.private?.join('\n');
    const sourceClassName = functionInfo.sourceClassName || '';
    let constructorsMethod = '';
    let classNameLower = sourceClassName?.toLowerCase();


    let gmockStr = '';
    allGmock.map(item => {
      gmockStr = gmockStr + `- ${item}\n`;
    });
    let cppstubStr = '';
    allCppStub.map(item => {
      cppstubStr = cppstubStr + `- ${item}\n`;
    });
    const filterPublicList = [];
    for (let i = 0; i < publicList.length; i++) {
      const item = publicList[i];
      const tree = this.treeSitterParser.getTree(item, languageId);
      if (!tree) {
        continue;
      }
      const funcName = this.treeSitterParser.getTargetNodeText(tree.rootNode, ['field_identifier', 'identifier'])[0]
      if (!item.trim().startsWith('~') && funcName === sourceClassName) {
        filterPublicList.push(item)
      }
    }
    if (filterPublicList.length) {
      constructorsMethod = filterPublicList.join('\n');
    } else {
      constructorsMethod = sourceClassName ? `${sourceClassName}()` : '';
    }
    return { constructorsMethod, classNameLower, gmockStr, cppstubStr, classFields };
  }
  
  public static getHeadMacroStr(gmockStr: string, cppstubStr: string, sourceHeaderFileStr: string, filterReferences: vscode.Location[]): string {
    return `#include "gtest/gtest.h"\n${gmockStr.length ? '#include "gmock/gmock.h"\n' : ''}${cppstubStr.length ? '#include "stub.h"\n' : ''}${filterReferences?.length ? `#define private public\n${sourceHeaderFileStr}` : ''}#undef private\n`;
  }

  public static async handleAllDefinitions(symbolDefinitions: Definitions, functionInfo: FunctionInfo, pathMap: PathMap[]) {
    const start = Date.now(); // 记录开始时间
    const ignoredFunc = ['sptr'];
    const memberVariables = Array.from(functionInfo.memberVariables || new Set());
    let funcCalledList: FuncCalledInfo[] = [];
    const definitions = symbolDefinitions;
    for (const value of Object.values(definitions)) {
      const definitionList: SnippetDefinition[] = (value as unknown) as SnippetDefinition[];
      for (let i = 0; i < definitionList.length; i++) {
        const item = definitionList[i];
        if (!item || !item.location || !item.type || !item.name || !item.text) {
          continue;
        }
        const filepath = item.location.uri.path;
        const fileSuffix = path.basename(filepath).split('.')[1] || '';
        const doc = await this.languageServer.getTextDocument(filepath);
        if (item.type === 'class') {
          // 类
          const functionInfoList = await this.getAllCalledFunctionsInfo(
            item, doc, memberVariables as string[], fileSuffix, functionInfo);
          funcCalledList = funcCalledList.concat(functionInfoList);
        } else if (item.type === 'function' && !ignoredFunc.includes(item.name) &&
          item.text && !item.text.includes('~')) {
          // 根据函数寻找类名
          const funtionInfoItem = await this.getCalledClassInfo(
            doc, doc.languageId, item, fileSuffix, functionInfo);
          if (funtionInfoItem) {
            funcCalledList.push(funtionInfoItem);
          }
        }
      }
    }
    const end = Date.now(); // 记录结束时间
    const executionTime = end - start; // 计算执行时间
    Logger.info(`handleAllDefinitions get funcCalledList time cost: ${executionTime}ms.`);
    return this.dealwithFuncCalledList(funcCalledList, pathMap);
  }

  // 由于文件太长，我将添加一个简化版本的其余方法
  // 在实际使用中，您需要添加完整的方法实现
  
  public static async getUTTest(
    document: vscode.TextDocument,
    unittestsDir: string,
    range?: vscode.Range
  ): Promise<{
    testCases: string[],
    testSuite: string,
    gMock: { key: string, value: string }[],
    cppStub: { key: string, value: string[] }[],
  }> {
    const start = Date.now(); // 记录开始时间
    if (range) {
      const references = await this.languageServer.getDocumentReferences( document, range.start);
      let testDir = unittestsDir;
      const testRefs = references.filter(item => {
        return item.uri.path.split('/').some((n: string) => n === testDir) && item.uri.path.endsWith('.cpp');
      });
      const file2Ref = new Map<string, vscode.Location[]>();
      testRefs.forEach(element => {
        if (file2Ref.has(element.uri.path)) {
          file2Ref.get(element.uri.path)?.push(element);
        } else {
          file2Ref.set(element.uri.path, [element]);
        }
      });
      for (const [file, refs] of file2Ref) {
        // doc：文档
        const doc = await this.languageServer.getTextDocument(file);
        // range:被引入的位置
        const ranges = refs.map(r => r.range);
        // 获取引用的HWTEST_F测试用例
        const testCases = await this.getTestCase(doc, ranges);
        // 筛选测试用例最多的测试类
        const selectedCases = this.mostFrequentItems<TestCase, string>(
          testCases, (item: TestCase) => item.testSuite.name);
        if (selectedCases.length) {
          // 获取测试类定义
          const testSuite = await this.getTestSuiteDefinition(doc, selectedCases[0].testSuite);
          // 获取mock类定义，只支持拿本文件中的
          const gMock = this.getGMockClassDefinition(doc);
          // 获取cpp-stub桩函数定义, 只支持拿本文件中的
          const cppStub = this.map2KeyVal(await this.getCppStubFunctionDefintion(doc, testCases));
          return { testCases: testCases.map(c => c.text), testSuite, gMock, cppStub };
        }
      }
    }
    const end = Date.now(); // 记录结束时间
    const executionTime = end - start; // 计算执行时间
      Logger.info(`getUTTest success time cost: ${executionTime}ms.`);
    return { testCases: [], testSuite: '', gMock: [], cppStub: [] };
  }

  /**
   * 获取测试用例
   * @param doc 文档对象
   * @param refRanges 引用范围数组
   * @returns 测试用例数组
   */
  private static async getTestCase(doc: vscode.TextDocument, refRanges: vscode.Range[]): Promise<TestCase[]> {
    if (!(doc && (doc.languageId === 'cpp' || doc.languageId === 'c'))) {
      return [];
    }
    const tree = this.treeSitterParser.getTree(doc.getText(), doc.languageId);
    if (!tree) {
      return [];
    }
    const testCases: TestCase[] = [];
    const stack: (SyntaxNode | undefined)[] = [tree?.rootNode];
    while (stack.length > 0) {
      const currentNode = stack.pop();
      if (!currentNode) {
        continue;
      };
      // 定位测试用例
      if (currentNode.type === 'expression_statement' && currentNode.text.startsWith('HWTEST_F') &&
        currentNode.nextNamedSibling?.type === 'compound_statement') {
        const testCaseRange = new vscode.Range(
          new vscode.Position(currentNode.startPosition.row, 0),
          ClassifyDefinitionsProcessor.getNodeRange(currentNode.nextNamedSibling).end
        );
        if (refRanges.some(r => testCaseRange.contains(r))) {
          // 获取测试类名
          const testSuiteNode = currentNode.child(0)?.childForFieldName('arguments')?.child(1);
          testSuiteNode && testCases.push({
            range: testCaseRange,
            text: doc.getText(testCaseRange),
            testSuite: {
              name: testSuiteNode.text,
              position: ClassifyDefinitionsProcessor.getNodeRange(testSuiteNode)
            }
          });
        }
        stack.pop();
      }
      // 查找目标代码块
      const currentRange = ClassifyDefinitionsProcessor.getNodeRange(currentNode);
      if (refRanges.some(r => currentRange.contains(r))) {
        stack.push(...currentNode.children.reverse());
      }
    }
    return testCases;
  }

  /**
   * 获取测试套件定义
   * @param document 文档对象
   * @param testSuite 测试套件信息
   * @returns 测试套件定义字符串
   */
  private static async getTestSuiteDefinition(
    document: vscode.TextDocument,
    testSuite: NameAndPos): Promise<string> {
    const definitions = await vscode.commands.executeCommand<vscode.Location[]>(
      'vscode.executeDefinitionProvider', document.uri, testSuite.position.start);
    for (const definition of definitions) {
      let defDoc: vscode.TextDocument = document;
      if (definition.uri.path !== document.uri.path) {
        defDoc = await this.languageServer.getTextDocument(definition.uri.path);
      }
      const defDocLines = defDoc.getText().split(getEOL(defDoc));
      // 找类定义
      const classDef = this.getFullDefinition(defDocLines, definition.range.start.line, '{', '}');
      if (classDef.length === 0) {
        continue;
      }

      // 找成员函数
      let methodDefs: string[][] = [];
      const methodNames: string[] = ['SetUpTestCase', 'TearDownTestCase', 'SetUp', 'TearDown'];
      for (let i = definition.range.start.line; i < defDocLines.length; i++) {
        const line = defDocLines[i];
        const idx = line.indexOf(testSuite.name + '::');
        if (idx < 0) {
          continue;
        }
        if (methodNames.some(n => line.slice(idx).startsWith(testSuite.name + '::' + n))) {
          methodDefs.push(this.getFullDefinition(defDocLines, i, '{', '}'));
        }
      }
      return [classDef.join('\n'), ...methodDefs.map(def => def.join('\n'))].join('\n\n');
    }
    return '';
  }

  /**
   * 获取GMock类定义
   * @param document 文档对象
   * @returns GMock类定义数组
   */
  private static getGMockClassDefinition(document: vscode.TextDocument): { key: string, value: string }[] {
    const result: { key: string, value: string }[] = [];
    let re = /class\s+(?<mock>\w+)\s*\:\s*public\s+(?<base>[\w:]+)/g;
    let match: RegExpExecArray | null;
    while (match = re.exec(document.getText())) {
      if (match.groups?.mock && match.groups?.base) {
        const className = match.groups?.base.split('::').pop();
        if (className) {
          result.push({ key: className, value: match.groups?.mock });
        }
      }
    }
    return result;
  }

  /**
   * 获取C++桩函数定义
   * @param document 文档对象
   * @param testCases 测试用例数组
   * @returns C++桩函数定义Map
   */
  private static async getCppStubFunctionDefintion(document: vscode.TextDocument, testCases: TestCase[]): Promise<Map<string, string[]>> {
    const result = new Map<string, string[]>();
    // 解析stub.set语句获取被桩函数和桩函数名
    for (const testcase of testCases) {
      const testCaseLines = testcase.text.split(getEOL(document));
      for (let i = 0; i < testCaseLines.length; i++) {
        const line = testCaseLines[i];
        const idx = line.indexOf('stub.set(');
        if (idx < 0) {
          continue;
        }
        const stubCall = this.getFullDefinition(testCaseLines, idx, '(', ')');
        if (stubCall.length <= 0) {
          continue;
        }
        const { className, methodName, stubFuncName } = await this.parseStubSetCall(
          document, stubCall.join('\n'));
        if (methodName && stubFuncName) {
          const key = `${className}#${methodName}`;
          if (result.has(key)) {
            result.get(key)?.push(stubFuncName);
          } else {
            result.set(key, [stubFuncName]);
          }
        }
      }
    }

    if (result.size <= 0) {
      return result;
    }

    // 找桩函数定义
    let stubFuncDefs: Map<string, string> = new Map<string, string>();
    const stubFuncNames: string[] = [...result.keys()];
    const stubFuncNameRegs: RegExp[] = stubFuncNames.map(n => new RegExp(`\\W${n}\\W`));
    const docLines: string[] = document.getText().split(getEOL(document));
    for (let i = 0; i < docLines.length; i++) {
      const line = docLines[i];
      for (let j = 0; j < stubFuncNames.length; j++) {
        if (stubFuncNameRegs[j].test(line)) {
          const def = this.getFullDefinition(docLines, i, '{', '}');
          if (def.length > 0) {
            stubFuncDefs.set(stubFuncNames[j], def.join('\n'));
          }
        }
      }
    }

    // 将结果中的桩函数名替换成定义
    for (const [key, names] of result) {
      let i = 0;
      while (i < names.length) {
        if (stubFuncDefs.has(names[i])) {
          names[i] = stubFuncDefs.get(names[i]) ?? '';
          i++;
        } else {
          names.splice(i, 1);
        }
      }
    }
    return result;
  }

  /**
   * 解析stub.set调用
   * @param doc 文档对象
   * @param stubCall stub.set调用代码
   * @returns 解析结果
   */
  private static async parseStubSetCall(doc: vscode.TextDocument, stubCall: string):
    Promise<{ className: string, methodName: string, stubFuncName: string }> {
    if (!(doc && (doc.languageId === 'cpp' || doc.languageId === 'c'))) {
      return { className: '', methodName: '', stubFuncName: '' };
    }

    let className: string = '';
    let methodName: string = '';
    let stubFuncName: string = '';
    const tree = this.treeSitterParser.getTree(stubCall, doc.languageId);

    const callExps = tree?.rootNode?.descendantsOfType('call_expression') ?? [];
    for (const call of callExps) {
      const argumentList = call.childForFieldName('arguments')?.children ?? [];
      // stub.set()固定两参数
      if (argumentList.length !== 2) {
        continue;
      }
      // 第二个参数为桩函数名
      if (argumentList[1].type !== 'identifier') {
        continue;
      }
      stubFuncName = argumentList[1].text;
      // 第一个参数可能是:
      //   OverloadFunc
      //   ADDR(DemoClass, OverloadFunc)
      //   static_cast<MemberFuncType1>(ADDR(DemoClass, OverloadFunc))
      if (argumentList[0].type === 'identifier') {
        methodName = argumentList[0].text;
        return { className, methodName, stubFuncName };
      } else if (argumentList[0].type === 'call_expression') {
        const funcNode = argumentList[0].childForFieldName('function');
        const funcArgNode = argumentList[0].childForFieldName('argument_list');
        if (funcNode?.text === 'ADDR' &&
          funcArgNode?.childCount === 2 &&
          funcArgNode?.child(0)?.type === 'identifier' &&
          funcArgNode?.child(1)?.type === 'identifier') {
          className = funcArgNode?.child(0)?.text ?? '';
          methodName = funcArgNode?.child(1)?.text ?? '';
          return { className, methodName, stubFuncName };
        }
        if (funcNode?.type === 'template_function' &&
          funcNode?.childForFieldName('name')?.text === 'static_cast' &&
          funcArgNode?.childCount === 1 &&
          funcArgNode?.child(0)?.type === 'call_expression') {
          const addrFuncNode = funcArgNode?.child(0)?.childForFieldName('function');
          const addrFuncArgNode = funcArgNode?.child(0)?.childForFieldName('arguments');
          if (addrFuncNode?.text === 'ADDR' &&
            addrFuncArgNode?.childCount === 2 &&
            addrFuncArgNode?.child(0)?.type === 'identifier' &&
            addrFuncArgNode?.child(1)?.type === 'identifier') {
            className = addrFuncArgNode?.child(0)?.text ?? '';
            methodName = addrFuncArgNode?.child(1)?.text ?? '';
            return { className, methodName, stubFuncName };
          }
        }
      }
    }
    return { className: '', methodName: '', stubFuncName: '' };
  }

  /**
   * 将Map转换为键值对数组
   * @param map Map对象
   * @returns 键值对数组
   */
  private static map2KeyVal<KeyType, ValType>(map: Map<KeyType, ValType>): { key: string, value: ValType }[] {
    const result: { key: string, value: ValType }[] = [];
    for (const [key, value] of map) {
      result.push({ key: String(key), value });
    }
    return result;
  }

  /**
   * 查找最频繁的项目
   * @param items 项目数组
   * @param attrfn 属性函数
   * @returns 最频繁的项目数组
   */
  private static mostFrequentItems<T, A>(items: T[], attrfn: (item: T) => A): T[] {
    const attrCnt = new Map<A, number>();
    items.forEach(item => {
      const attr = attrfn(item);
      const curVal = attrCnt.get(attr);
      if (curVal) {
        attrCnt.set(attr, curVal + 1);
      } else {
        attrCnt.set(attr, 1);
      }
    });
    let maxCnt = 0;
    let maxAttr: A | undefined = undefined;
    for (const [key, cnt] of attrCnt) {
      if (cnt > maxCnt) {
        maxCnt = cnt;
        maxAttr = key;
      }
    }
    if (maxCnt > 0) {
      return items.filter(item => attrfn(item) === maxAttr);
    }
    return [];
  }

  /**
   * 获取完整定义
   * @param docLines 文档行数组
   * @param startLineNumber 开始行号
   * @param leftBoundary 左边界字符
   * @param rightBoundary 右边界字符
   * @returns 定义行数组
   */
  private static getFullDefinition(
    docLines: string[],
    startLineNumber: number,
    leftBoundary: string,
    rightBoundary: string): string[] {
    let curLineNumber: number = startLineNumber;
    let leftBracketCnt: number = 0;
    let rightBracketCnt: number = 0;
    const result: string[] = [];
    while (curLineNumber < docLines.length) {
      const curLine = docLines[curLineNumber];
      curLineNumber++;
      for (const char of curLine) {
        if (char === leftBoundary) {
          leftBracketCnt = leftBracketCnt + 1;
        } else if (char === rightBoundary) {
          rightBracketCnt = rightBracketCnt + 1;
        }
      }
      result.push(curLine);
      if (leftBracketCnt === rightBracketCnt && leftBracketCnt > 0) {
        break;
      }
    }
    // 如果括号未正常配对，将定义置空
    if (!(leftBracketCnt === rightBracketCnt && leftBracketCnt > 0)) {
      return [];
    }
    return result;
  }

  private static dealwithFuncCalledList(funcCalledList: FuncCalledInfo[], pathMap: PathMap[]): {
    gmockTemplateStr: string, cppStubTemplateStr: string,
    setFuncCalledList: FuncCalledInfo[], interfaceDefinitions: string[],
    allGmock: string[], allCppStub: string[], otherStr: string
  } {
    const setFuncCalledList: FuncCalledInfo[] = [];
    let gmockTemplateStr: string = '';
    let cppStubTemplateStr: string = '';
    let otherStr: string = '';
    const interfaceDefinitions: string[] = [];
    const allCppStub: string[] = [];
    const allGmock: string[] = [];
    funcCalledList.forEach((item) => {
      const check = setFuncCalledList.find((checkIntem) => {
        return checkIntem.sourceFuncName === item.sourceFuncName;
      });
      if (check) {
        return;
      }
      setFuncCalledList.push(item);
      // static要判断是否是全局函数
      if (item.isStatic && item.isGlobleFun) {
        otherStr = otherStr + `- ${item.signature};\n`;
        return;
      }
      if (item.isVirtual) {
        const str = '请注意，需要遵循`助理示例`的测试格式，使用gmock对' +
          `'${item.sourceClassName}'类的'${item.sourceFuncName}'函数进行打桩，需要mock'${item.sourceFuncName}'方法。`;
        pathMap.forEach((path) => {
          if (path.lastRow && path.lastRow > item.locationRow) {
            path.gmockTemplateStrList && path.gmockTemplateStrList.push(str);
          }
        });
        gmockTemplateStr = gmockTemplateStr + str + '\r\n';
        const interfaceDefinition = 'class ' + `${item.sourceClassName} {`
          + '\r\npublic:' + `\r\n    ${item.virtualFunction}` + '\r\n};';
        interfaceDefinitions.push(interfaceDefinition);
        allGmock.push(item.signature);
      } else {
        const str = `请注意，被测函数调用的'${item.sourceFuncName}'函数不是虚函数，` +
          '需要遵循`助理示例`的测试格式，' + `需要使用cpp-stub对'${item.sourceClassName}'类的'${item.declarator}'函数进行打桩`;
        pathMap.forEach((path) => {
          if (path.lastRow && path.lastRow > item.locationRow) {
            path.cppStubTemplateStrList && path.cppStubTemplateStrList.push(str);
          }
        });
        cppStubTemplateStr = cppStubTemplateStr + str + '\r\n';
        allCppStub.push(item.signature);
      }
    });
    pathMap.forEach((path) => {
      let cppStubStr = '';
      Array.from(new Set(path.cppStubTemplateStrList)).forEach(str =>
        cppStubStr = cppStubStr + str + '\r\n'
      );
      path.cpp_stub_template_str = cppStubTemplateStr;
      let gmockStr = '';
      Array.from(new Set(path.gmock_template_str)).forEach(str =>
        gmockStr = gmockStr + str + '\r\n'
      );
    });
    return { gmockTemplateStr, cppStubTemplateStr, setFuncCalledList, interfaceDefinitions, allGmock, allCppStub, otherStr };
  }

  private static async getAllCalledFunctionsInfo(
    codeDefinition: SnippetDefinition,
    document: vscode.TextDocument,
    memberVariables: string[],
    fileSuffix: string,
    functionInfo: FunctionInfo): Promise<FuncCalledInfo[]> {
    const functionSymbols: FuncCalledInfo[] = [];
    const tree = this.treeSitterParser.getTree(codeDefinition.text, document.languageId)
    if (!tree) {
      return [];
    }
    const stack: any[] = [tree.rootNode];
    const className = this.treeSitterParser.getTargetNodeText(tree.rootNode, ['type_identifier'])[0];
    while (stack.length > 0) {
      const currentNode = stack.pop();
      let funcNode: SyntaxNode | null = null;
      if (currentNode.type === 'function_definition') {
        funcNode = currentNode;
      } else if (currentNode.type === 'field_declaration') {
        const funcList = currentNode.descendantsOfType('function_declarator');
        if (funcList?.length) {
          funcNode = currentNode;
        }
      }
      const funcDeclarList = currentNode.descendantsOfType('function_declarator');
      if (funcNode && funcDeclarList?.length) {
        const funcDeclar = funcDeclarList[0];
        const text = currentNode.text;
        const funcName = this.treeSitterParser.getTargetNodeText(funcNode, ['field_identifier', 'identifier'])[0];
        const isSameNameFunc = funcName === functionInfo.sourceFuncName;
        const isSelfFunc = isSameNameFunc && className === functionInfo?.sourceClassName;
        let isSubItem = false;
        if (isSameNameFunc && !isSelfFunc) {
          const position = this.getClassPosition(codeDefinition);
          // 查找子节点是否包含被测函数所在类
          isSubItem = await this.isSubHierarchyItem(document, position, functionInfo?.sourceClassName);
        }
        if (funcName && funcName !== className && !text.includes('~') && memberVariables.includes(funcName) && !isSelfFunc && !isSubItem) {
          let row = this.getFunctionSymbols(functionInfo.code || '', className, true);
          const virtualList = this.treeSitterParser.getTargetNodeText(currentNode, ['virtual']);
          let isVirtual: boolean = virtualList.length > 0;
          const signature = text.split('\n')?.filter((item: string) => item.trim())?.join(' ');
          let classNamespace = '';
          let parameter = '';
          let returnType = '';
          if (isVirtual) {
            const name = codeDefinition?.name;
            const range = codeDefinition?.location.range;
            classNamespace = await this.getClassNamespace(name, range, document);
            parameter = this.treeSitterParser.getTargetNodeText(funcNode, ['parameter_list'])[0];
            returnType = this.treeSitterParser.getTargetNodeText(funcNode, ['qualified_identifier'])[0];
          }
          const funcInfo = {
            sourceClassName: className,
            sourceFuncName: funcName,
            declarator: funcDeclar.text,
            isGlobleFun: fileSuffix === 'h',
            isVirtual,
            isStatic: this.treeSitterParser.getTargetNodeText(currentNode, ['storage_class_specifier'])[0] === 'static',
            locationRow: row,
            virtualFunction: isVirtual ? text : '',
            signature: signature.trim().endsWith(';') ? signature.slice(0, -1) : signature,
            classNamespace,
            parameter,
            returnType
          };
          functionSymbols.push(funcInfo);
        }
      }
      for (let i = currentNode.childCount - 1; i >= 0; i--) {
        stack.push(currentNode.child(i));
      }
    }
    return functionSymbols;
  }

  private static async getCalledClassInfo(
    doc: vscode.TextDocument,
    language: string,
    funcSymbols: SnippetDefinition,
    fileSuffix: string,
    functionInfo: FunctionInfo): Promise<FuncCalledInfo | null> {
    if (doc && (language === 'cpp' || language === 'c')) {
      const tree = this.treeSitterParser.getTree(doc.getText(), language)
      if (!tree) {
        return null;
      }
      const classSpecifier: SyntaxNode[] = tree.rootNode.descendantsOfType('class_specifier');
      for (const currentNode of classSpecifier) {
        const startPosition = currentNode.startPosition.row;
        const endPosition = currentNode.endPosition.row;
        const funPosition = funcSymbols.location.range.start.line;
        // 通过位置判断是该函数所在的类
        if (funPosition >= startPosition && funPosition <= endPosition) {
          // 有可能获取到虚函数的重写，需要判断是否有继承类，其中是否有同名虚函数
          const baseClassNode = this.getTargetClassFormBaseClass(currentNode, classSpecifier);
          const classNode = baseClassNode || currentNode;
          const classNameNode = this.treeSitterParser.getTargetNode(classNode, ['type_identifier'])[0];
          const classNameText = classNameNode?.text;
          // "Compiler"模式获取的函数可能结构不完整，需要从类中获取完整的函数
          const funcNode = this.getFunNodeFromClass(language, funcSymbols, classNode, funPosition);
          if (!funcNode) {
            return null;
          }
          //   int size() 会被解析为 init_declarator
          //   int size(); 才会被解析为 function_declarator
          const funcDeclar = funcNode.descendantsOfType('function_declarator');
          const funcName = this.treeSitterParser.getTargetNodeText(funcDeclar[0], ['field_identifier', 'identifier'])[0];
          if (!funcName) {
            return null;
          }
          const isSameNameFunc = funcName === functionInfo.sourceFuncName;
          const isSelfFunc = isSameNameFunc && classNameText === functionInfo?.sourceClassName;
          let isSubItem = false;
          if (isSameNameFunc && !isSelfFunc && classNameNode) {
            const position = new vscode.Position(classNameNode.startPosition.row, classNameNode.startPosition.column)
            isSubItem = await this.isSubHierarchyItem(doc, position, functionInfo?.sourceClassName);
          }
          if (isSelfFunc || funcName === classNameText || isSubItem) {
            return null;
          }
          let row = this.getFunctionSymbols(functionInfo.code || '', funcName, false);
          const signature = funcNode.text.split('\n')?.filter((item: string) => item.trim())?.join(' ');
          const isVirtual = this.treeSitterParser.getTargetNodeText(funcNode, ['virtual'])?.length > 0;
          let classNamespace = '';
          let parameter = '';
          let returnType = '';
          if (isVirtual) {
            const start = new vscode.Position(startPosition, classNode.startPosition.column);
            const end = new vscode.Position(endPosition, classNode.endPosition.column);
            const range = new vscode.Range(start, end);
            const name = classNameText;
            classNamespace = await this.getClassNamespace(name, range, doc);
            parameter = this.treeSitterParser.getTargetNodeText(funcNode, ['parameter_list'])[0];
            returnType = this.treeSitterParser.getTargetNodeText(funcNode, ['qualified_identifier', 'primitive_type'])[0];
          }
          const funcInfo = {
            sourceClassName: classNameText,
            sourceFuncName: funcName,
            declarator: funcDeclar[0]?.text,
            isGlobleFun: fileSuffix === 'h',
            isVirtual,
            isStatic: this.treeSitterParser.getTargetNodeText(funcDeclar[0], ['storage_class_specifier'])[0] === 'static',
            locationRow: row,
            virtualFunction: funcNode.text,
            signature: signature.trim().endsWith(';') ? signature.slice(0, -1) : signature,
            classNamespace,
            parameter,
            returnType
          };
          return funcInfo;
        }
      }
    }
    return null;
  }

  private static getTargetClassFormBaseClass(node: SyntaxNode, classSpecifier: SyntaxNode[]): SyntaxNode | null {
    const classList = this.treeSitterParser.getTargetNode(node, ['base_class_clause']);
    if (!classList) {
      return null;
    }
    const baseClassName = this.treeSitterParser.getTargetNode(classList[0], ['type_identifier'])[0];
    if (!baseClassName?.text) {
      return null;
    }
    const baseClassNode = classSpecifier.find((item: SyntaxNode) => {
      const classNode = this.treeSitterParser.getTargetNode(item, ['type_identifier'])[0];
      const className = classNode?.text;
      return className === baseClassName.text;
    })
    return baseClassNode || null;
  }

  private static getFunNodeFromClass(language: string, funcSymbols: SnippetDefinition, classNode: SyntaxNode, funPosition: Number): SyntaxNode | null {
    const text = funcSymbols.text?.trim()?.endsWith(';') ? funcSymbols.text : funcSymbols.text + ';';
    const funcTree = this.treeSitterParser.getTree(text, language)
    const funcName = this.getFuncNameText(funcTree?.rootNode || null);
    const funNodeList = this.treeSitterParser.getTargetNode(classNode, ['field_declaration']);
    const funcNode = funNodeList.find(node => {
      const itemFuncName = this.getFuncNameText(node);
      return (node.startPosition.row === funPosition) || itemFuncName === funcName;
    });
    return funcNode || funcTree?.rootNode || null;
  }

  private static getFuncNameText(node: SyntaxNode | null): string {
    if (!node) {
      return '';
    }
    const functionDefinition = node.descendantsOfType('function_declarator');
    const res = this.treeSitterParser.getTargetNodeText(functionDefinition[0], ['field_identifier', 'identifier'])[0];
    return res;
  }

  private static getClassPosition(codeDefinition: SnippetDefinition) {
    const character = codeDefinition.text.indexOf(codeDefinition.name);
    const position = new vscode.Position(codeDefinition.location.range.start.line, character)
    return position
  }

  private static async isSubHierarchyItem(doc: vscode.TextDocument, position: vscode.Position, className: string | undefined): Promise<boolean> {
    const start = Date.now(); // 记录开始时间
    const uri: vscode.Uri = doc.uri;
    if (!position) {
      return false;
    }
    const rootHierarchyList = await vscode.commands.executeCommand<vscode.TypeHierarchyItem[]>('vscode.prepareTypeHierarchy', uri, position);
    if (!rootHierarchyList) {
      return false;
    }
    let stack = rootHierarchyList;
    while (stack.length > 0) {
      const currentType = stack.pop()
      if (!currentType) {
        continue;
      }
      if (currentType.name === className) {
        return true;
      }
      const nextHierarchyList = await vscode.commands.executeCommand<vscode.TypeHierarchyItem[]>('vscode.provideSubtypes', currentType);
      stack = stack.concat(nextHierarchyList)
    }
    // 查找子节点
    const end = Date.now(); // 记录结束时间
    const executionTime = end - start; // 计算执行时间
    Logger.info(`isSubHierarchyItem time cost: ${executionTime}ms.`);
    return false
  }

  private static getFunctionSymbols(functionText: string, funcName: string, isClass: boolean): any {
    let rows: Number[] = [];
    let row = 0;
    for (const line of functionText.split('\n')) {
      if (line.indexOf(isClass ? funcName : funcName + '(') > 0) {
        rows.push(row);
      }
      row++;
    }
    if (rows.length > 0) {
      return rows[rows.length - 1];
    }
    return row;
  }

  private static async getClassNamespace(name: string, range: vscode.Range, doc: vscode.TextDocument) {
    const symbolChain = await ClassifyDefinitionsProcessor.getSymbolChain(null, doc, name, range);
    let nestedNamespaces: string[] = [];
    const extractDetail = async (symbolChain: vscode.DocumentSymbol[], index: number) => {
      if (symbolChain.length <= index) {
        return;
      }
      const s = symbolChain[index];
      // tag模式下，"#ifndef ALGORITHM_CAMERA_DATA_LISTENER_H"会被识别为namespace
      if (s?.kind === vscode.SymbolKind.Namespace && (!s?.name?.startsWith('#'))) {
        if (s?.name) {
          nestedNamespaces.push(s.name);
        }
        if (symbolChain.length > index + 1) {
          await extractDetail(symbolChain, index + 1);
        }
      } else {
        await extractDetail(symbolChain, index + 1);
      }
    };
    await extractDetail(symbolChain, 0);
    const classNamespace = nestedNamespaces.join('::');
    return classNamespace;
  }
}